// ==UserScript==
// @name					Popup Search
// @author					lkytal
// @namespace				Lkytal
// @homepage				https://lkytal.github.io/
// @description				Popup search box and translate button (etc) for selected texts
// @include					*
// @exclude					*/test/*.html*
// @exclude					http://acid3.acidtests.org/*
// @exclude					http://www.acfun.tv/*
// @exclude					http://www.sf-express.com/*
// @require					https://cdn.bootcss.com/jquery/3.1.1/jquery.min.js
// @version					4.1.1
// @icon					http://lkytal.qiniudn.com/ic.ico
// @grant					GM_xmlhttpRequest
// @grant					GM_addStyle
// @grant					unsafeWindow
// @grant					GM_openInTab
// @grant					GM_setClipboard
// @grant					GM_download
// @grant					GM_getValue
// @grant					GM_setValue
// @grant					GM_registerMenuCommand
// @charset					UTF-8
// @homepageURL				https://git.oschina.net/coldfire/GM
// @updateURL				https://git.oschina.net/coldfire/GM/raw/master/meta/popsearch.meta.js
// @downloadURL				https://git.oschina.net/coldfire/GM/raw/master/popsearch.user.js
// ==/UserScript==

"use strict";;
var CopyText, GetOpt, InTextBox, OpenSet, PopupInit, PopupLoad, ReadOpt, SaveOpt, SettingWin, ShowBar, TimeOutHide, UpdateLog, UpdateNotificated, addAditionalCSS, addCSS, ajaxError, doRequest, fixPos, getLastRange, get_selection_offsets, isChrome, log, onTranslate, popData, praseTranslationGoogle,
  hasProp = {}.hasOwnProperty;

window.$ = this.$ = this.jQuery = jQuery.noConflict(true);

popData = {
  count: 0,
  mouseIn: 0,
  bTrans: 0,
  additionalCSSLoaded: 0,
  codeVersion: 8,
  text: "",
  icons: {
    baiduIcon: "",
    bingIcon: "",
    translateIcon: "",
    googleIcon: "",
    linkIcon: "",
    taobaoIcon: "",
    yahooIcon: "",
    wikiIcon: "",
    jdIcon: "",
    eBayIcon: "",
    doubanIcon: "",
    amazonIcon: "",
    youkuIcon: "",
    youtubeIcon: "",
    tiebaIcon: "",
    inSiteIcon: '',
    settingIcon: "",
    tipdown: "",
    tipup: "",
    pending: ""
  },
  optionList: [
    {
      id: "Fade_st",
      text: "超时自动隐藏 / Hide after timeout",
      defaultValue: 1
    }, {
      id: "Dis_st",
      text: "显示于文字上方 / Display above selection",
      defaultValue: 1
    }, {
      id: "Tab_st",
      text: "新标签页打开 / Open in new tabs",
      defaultValue: 1
    }, {
      id: "Focus_st",
      text: "前台标签页打开 / Force foreground tabs",
      defaultValue: 1
    }, {
      id: "Iframe_st",
      text: "在Iframe中显示/ Load in iframes",
      defaultValue: 0
    }, {
      id: "Copy_st",
      text: "自动复制选中文字 / Auto copy selections",
      defaultValue: 0
    }, {
      id: "Ctrl_st",
      text: "仅按下Ctrl时显示 / Only when ctrl pressed",
      defaultValue: 0
    }, {
      id: "userEngine_st",
      text: "自定义引擎 / Enable Customize",
      defaultValue: 0
    }
  ],
  userEngines: [],
  defaultEngines: [
    {
      id: "UserEngine",
      title: "Example of User Engine",
      description: "自定义引擎示例 / Example of user engine",
      src: "http://lkytal.qiniudn.com/ic.ico",
      href: "https://www.google.com/search?newwindow=1&safe=off&q=${text}"
    }, {
      id: "UserEngine2",
      title: "Example Engine use dataURL",
      description: "DataURL引擎示例 / Example Engine use dataURL",
      src: "",
      href: "https://www.google.com/search?q=${text}%20site:${domain}"
    }
  ]
};

popData.engines = [
  {
    id: "Open_st",
    title: "Open As Url",
    description: "选中文本视作链接打开 / Open selection as url",
    defaultState: 0,
    src: popData.icons.linkIcon,
    href: '${rawText}'
  }, {
    id: "Site_st",
    title: "Search Current Website",
    description: "在当前网站内搜索 / Search in current website",
    defaultState: 1,
    src: popData.icons.inSiteIcon,
    href: 'https://www.google.com/search?newwindow=1&safe=off&q=${text}%20site:${domain}'
  }, {
    id: "Bing_st",
    title: "Search with Bing",
    description: "必应搜索 / Search with Bing",
    defaultState: 1,
    src: popData.icons.bingIcon,
    href: 'https://bing.com/search?q=${text}&form=MOZSBR'
  }, {
    id: "Baidu_st",
    title: "Search with Baidu",
    description: "百度搜索 / Search with Baidu",
    defaultState: 1,
    src: popData.icons.baiduIcon,
    href: 'https://www.baidu.com/s?wd=${text}&ie=utf-8'
  }, {
    id: "Google_st",
    title: "Search with Google",
    description: "谷歌搜索 / Search with Google",
    defaultState: 1,
    src: popData.icons.googleIcon,
    href: 'https://www.google.com/search?newwindow=1&safe=off&q=${text}'
  }, {
    id: "Yahoo_st",
    title: "Search with Yahoo",
    description: "雅虎搜索 / Search with Yahoo",
    defaultState: 0,
    src: popData.icons.yahooIcon,
    href: 'https://search.yahoo.com/search;?p=${text}&ei=UTF-8'
  }, {
    id: "Taobao_st",
    title: "Search with Taobao",
    description: "搜索淘宝 / Search with Taoabo",
    defaultState: 1,
    src: popData.icons.taobaoIcon,
    href: 'https://s.taobao.com/search?q=${text}'
  }, {
    id: "Tieba_st",
    title: "Search in Tieba",
    description: "搜索贴吧 / Search with Tieba",
    defaultState: 0,
    src: popData.icons.tiebaIcon,
    href: 'http://tieba.baidu.com/f/search/res?ie=utf-8&qw=${text}'
  }, {
    id: "youtube_st",
    title: "Search with Youtube",
    description: "搜索Youtube / Search with Youtube",
    defaultState: 1,
    src: popData.icons.youtubeIcon,
    href: 'https://www.youtube.com/results?search_query=${text}'
  }, {
    id: "youku_st",
    title: "Search with Youku",
    description: "搜索优酷 / Search with Youku",
    defaultState: 0,
    src: popData.icons.youkuIcon,
    href: 'http://www.soku.com/search_video/q_${text}'
  }, {
    id: "amazon_st",
    title: "Search with Amazou",
    description: "搜索亚马逊/ Search with Amazon",
    defaultState: 1,
    src: popData.icons.amazonIcon,
    href: 'https://www.amazon.com/s/field-keywords=${text}'
  }, {
    id: "eBay_st",
    title: "Search with eBay",
    description: "搜索eBay / Search with eBay",
    defaultState: 0,
    src: popData.icons.eBayIcon,
    href: 'http://www.ebay.com/sch/i.html?_nkw=${text}&_sacat=0'
  }, {
    id: "douban_st",
    title: "Search with Douban",
    description: "搜索豆瓣电影 / Search with Douban Movie",
    defaultState: 0,
    src: popData.icons.doubanIcon,
    href: 'https://movie.douban.com/subject_search?search_text=${text}'
  }, {
    id: "jd_st",
    title: "Search with JD",
    description: "搜索京东 / Search with JD",
    defaultState: 0,
    src: popData.icons.jdIcon,
    href: 'https://search.jd.com/Search?keyword=${text}&enc=utf-8'
  }, {
    id: "Wiki_st",
    title: "Search with Wiki",
    description: "搜索维基百科 / Search with Wikipedia",
    defaultState: 0,
    src: popData.icons.wikiIcon,
    href: 'https://wikipedia.org/wiki/${text}'
  }
];

log = function(msg) {
  popData.count += 1;
  return console.log("Popup Msg " + popData.count + " : " + msg);
};

isChrome = function() {
  if (navigator.userAgent.indexOf("Chrome") > -1) {
    return true;
  }
};

fixPos = function(sel, e) {
  var eventLeft, eventTop, fix, m_left, offsetLeft, offsetTop, offsets;
  offsets = get_selection_offsets(sel);
  offsetTop = offsets[0];
  offsetLeft = offsets[1];
  if (e != null) {
    eventTop = e.pageY;
    eventLeft = e.pageX;
    if (Math.abs(offsetTop - eventTop) > 50) {
      offsetTop = eventTop - 8;
    }
    if (Math.abs(offsetLeft - eventLeft) > 50) {
      offsetLeft = eventLeft + 10;
    }
  } else {
    $('#showupbody').css('margin-left', '60px');
  }
  if (GetOpt('Dis_st')) {
    offsetTop = offsetTop - 2 - $('#ShowUpBox').height();
    if ((offsetTop - document.documentElement.scrollTop) < 40) {
      offsetTop = document.documentElement.scrollTop + 40;
    }
  } else {
    offsetTop += 1.1 * offsets[2];
  }
  m_left = $('#ShowUpBox').width();
  fix = 0;
  if (offsetLeft - m_left < 4) {
    fix = 4 - offsetLeft + m_left;
  }
  $('#ShowUpBox').css("top", offsetTop + "px").css("left", (offsetLeft - m_left + fix) + "px");
  return $('#popuptip').css('margin-left', m_left - 20 - fix);
};

$(document).mousedown(function(event) {
  if (popData.bTrans === 1) {
    PopupInit();
  }
  return $('#ShowUpBox').hide();
});

TimeOutHide = function() {
  if (popData.mouseIn === 0 && GetOpt("Fade_st") && !popData.bTrans) {
    return $('#ShowUpBox').fadeOut(600);
  }
};

PopupInit = function() {
  var $DivBox, $icon, EngineList, engine, j, k, l, len, len1, len2, ref, ref1, ref2;
  $('#ShowUpBox').remove();
  EngineList = "<a id='gtrans'><img title='Translate' src='" + popData.icons.translateIcon + "' /></a>";
  ref = popData.engines;
  for (j = 0, len = ref.length; j < len; j++) {
    engine = ref[j];
    EngineList += "<a id='" + engine.id + "Icon' href=''><img title='" + engine.title + "' src='" + engine.src + "' /></a>";
  }
  if (GetOpt("userEngine_st")) {
    ref1 = popData.userEngines;
    for (k = 0, len1 = ref1.length; k < len1; k++) {
      engine = ref1[k];
      EngineList += "<a id='" + engine.id + "Icon' href=''><img title='" + engine.title + "' src='" + engine.src + "' /></a>";
    }
  }
  $('body').append("<span id=\"ShowUpBox\"> <span id=\"showupbody\"> <span id=\"popupwapper\"> " + EngineList + " </span> <span id=\"Gspan\" /> </span> </span>");
  $DivBox = $('#ShowUpBox');
  $DivBox.hide();
  $DivBox.on("click mousedown dblclick mouseup", function(event) {
    return event.stopPropagation();
  });
  $DivBox.hover(function() {
    $(this).fadeTo(150, 1);
    return popData.mouseIn = 1;
  }, function() {
    if (popData.bTrans === 0 && $(this).is(":visible") && $(this).attr("opacity") === 1) {
      $(this).fadeTo(300, 0.7);
      clearTimeout(popData.timer);
      popData.timer = setTimeout(TimeOutHide, 6000);
    }
    return popData.mouseIn = 0;
  });
  $('#popupwapper').on("mouseup", function(event) {
    if (event.which === 3) {
      CopyText();
      $('#ShowUpBox').fadeOut(200);
      return false;
    } else if (event.which === 2) {
      GM_openInTab(document.defaultView.getSelection().toString());
      return false;
    }
  });
  $('#popupwapper').on("contextmenu", function(event) {
    return false;
  });
  $('#gtrans').on("click", onTranslate);
  ref2 = popData.engines;
  for (l = 0, len2 = ref2.length; l < len2; l++) {
    engine = ref2[l];
    $icon = $("#" + engine.id + "Icon");
    if (!GetOpt(engine.id)) {
      $icon.hide();
    }
    $icon.on("click", function(e) {
      if (isChrome()) {
        GM_openInTab($(this).attr('href'), {
          active: GetOpt("Focus_st") === 1
        });
      } else {
        GM_openInTab($(this).attr('href'), !GetOpt("Focus_st"));
      }
      $('#ShowUpBox').fadeOut(200);
      return false;
    });
  }
  if (GetOpt('Tab_st')) {
    $DivBox.find('a').attr('target', '_blank');
  } else {
    $DivBox.find('a').attr('target', '_self');
  }
  if (GetOpt('Dis_st')) {
    popData.tip = popData.tipup;
    return $DivBox.append('<span id="popuptip" class="tipup"></span>');
  } else {
    popData.tip = popData.tipdown;
    return $DivBox.prepend('<span id="popuptip" class="tipdown"></span>');
  }
};

ajaxError = function(res) {
  return $('#Gspan').empty().append("<p>Translate Error:<br />" + res.statusText + "</p>").show();
};

onTranslate = function(event) {
  event.preventDefault();
  popData.bTrans = 1;
  $("#Gspan").empty().append("<div style='padding:10px;'><img src='" + popData.icons.pending + "' /></div>").show();
  $('#popupwapper').hide();
  fixPos(document.defaultView.getSelection());
  return doRequest(0, 1000);
};

doRequest = function(i, wait) {
  var ErrHandle;
  ErrHandle = function() {
    return doRequest(i + 1, wait + 2000);
  };
  if (i >= 2) {
    ErrHandle = ajaxError;
  }
  return GM_xmlhttpRequest({
    method: 'POST',
    url: 'https://translate.google.cn/translate_a/single',
    data: "client=gtx&dj=1&q=" + popData.text + "&sl=auto&tl=auto&ie=UTF-8&oe=UTF-8&source=icon&dt=t&dt=bd",
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    timeout: wait,
    onload: praseTranslationGoogle,
    onerror: ErrHandle,
    ontimeout: ErrHandle
  });
};

praseTranslationGoogle = function(responseDetails) {
  var PickMeaning, Result, Rline, Rtxt, line, sentence;
  if (!popData.bTrans) {
    return;
  }
  try {
    Rtxt = JSON.parse(responseDetails.responseText);
  } catch (error) {
    return ajaxError(responseDetails);
  }
  Rline = (function() {
    var j, len, ref, results;
    ref = Rtxt.sentences;
    results = [];
    for (j = 0, len = ref.length; j < len; j++) {
      sentence = ref[j];
      results.push(sentence.trans);
    }
    return results;
  })();
  PickMeaning = function(list) {
    var i, item, j, len, results;
    results = [];
    for (i = j = 0, len = list.length; j < len; i = ++j) {
      item = list[i];
      if (item.score > 0.005 || i < 3) {
        results.push(item.word);
      }
    }
    return results;
  };
  if (Rtxt.dict != null) {
    Rline += (function() {
      var j, len, ref, results;
      ref = Rtxt.dict;
      results = [];
      for (j = 0, len = ref.length; j < len; j++) {
        line = ref[j];
        results.push("<br>" + (line.pos + " : " + (PickMeaning(line.entry))));
      }
      return results;
    })();
  }
  Result = "<div id=\"tranRst\" style=\"font-size:13px;overflow:auto;padding:5px 12px;\"> <div style=\"line-height:200%;font-size:13px;\"> " + Rline + " </div> </div>";
  $('#Gspan').empty().append(Result).show();
  fixPos(document.defaultView.getSelection());
};

$(document).on("mouseup", function(event) {
  if (event.which !== 1) {
    return;
  }
  if (GetOpt('Ctrl_st') && !event.ctrlKey) {
    return;
  }
  return ShowBar(event);
});

InTextBox = function(selection, event) {
  var area, j, len, ref;
  if ($(event.target).is('textarea, input[type=text], input[type=search], *[contenteditable="true"]')) {
    return true;
  }
  ref = $('textarea, input[type=text], *[contenteditable="true"]', document);
  for (j = 0, len = ref.length; j < len; j++) {
    area = ref[j];
    if (selection.containsNode(area, true)) {
      return true;
    }
  }
  return false;
};

ShowBar = function(event) {
  var engine, j, k, len, len1, paraList, ref, ref1, sel, setHref;
  sel = document.defaultView.getSelection();
  popData.rawText = sel.toString();
  popData.text = encodeURIComponent(popData.rawText);
  if (popData.rawText === '' || InTextBox(sel, event)) {
    return;
  }
  if (GetOpt("Copy_st")) {
    CopyText(popData.rawText);
  }
  $('#Gspan').empty().hide();
  paraList = {
    "\\${rawText}": popData.rawText,
    "\\${text}": popData.text,
    "\\${domain}": document.domain,
    "\\${url}": location.href
  };
  setHref = function(engine) {
    var href, para, value;
    href = engine.href;
    for (para in paraList) {
      if (!hasProp.call(paraList, para)) continue;
      value = paraList[para];
      href = href.replace(RegExp("" + para, "g"), value);
    }
    return $("#" + engine.id + "Icon").attr("href", href);
  };
  ref = popData.engines;
  for (j = 0, len = ref.length; j < len; j++) {
    engine = ref[j];
    setHref(engine);
  }
  ref1 = popData.userEngines;
  for (k = 0, len1 = ref1.length; k < len1; k++) {
    engine = ref1[k];
    setHref(engine);
  }
  if (popData.rawText.indexOf('http://') === -1 && popData.rawText.indexOf('https://') === -1) {
    $('#Open_stIcon').attr('href', "http://" + popData.rawText);
  }
  popData.mouseIn = 0;
  popData.bTrans = 0;
  clearTimeout(popData.timer);
  popData.timer = setTimeout(TimeOutHide, 6000);
  fixPos(sel, event);
  return $('#ShowUpBox').css('opacity', 0.9).fadeIn(150);
};

CopyText = function(seltxt) {
  var e;
  if (seltxt == null) {
    seltxt = document.defaultView.getSelection().toString();
  }
  try {
    return GM_setClipboard(seltxt, "text");
  } catch (error) {
    e = error;
    if (GetOpt("Copy_st")) {
      alert("ERROR: Auto copying not supported and will be disabled now");
      return SetOpt("Copy_st", 0);
    }
  }
};

GetOpt = function(id) {
  return GM_getValue(id);
};

SaveOpt = function(id) {
  return GM_setValue(id, $("#" + id + " > input").prop("checked") + 0);
};

ReadOpt = function(id) {
  return $("#" + id + " > input").prop("checked", GM_getValue(id));
};

OpenSet = function() {
  if ($('#popup_setting_bg').length === 0) {
    SettingWin();
  }
  return $('#popup_setting_bg').fadeIn(400);
};

SettingWin = function() {
  var chsJSON, engJSON, engine, engineOptionList, generateEngineOption, generateOption, item, j, len, option, optionList, ref;
  addAditionalCSS();
  $('#popup_setting_bg').remove();
  generateOption = function(option) {
    return "<span id='" + option.id + "' class='setting_item'> <img src=" + popData.icons.settingIcon + " /> <span class='text'>" + option.text + "</span> <input class='tgl tgl-flat' id='" + option.id + "_checkbox' type='checkbox'> <label class='tgl-btn' for='" + option.id + "_checkbox'></label> </span>";
  };
  optionList = ((function() {
    var j, len, ref, results;
    ref = popData.optionList;
    results = [];
    for (j = 0, len = ref.length; j < len; j++) {
      option = ref[j];
      results.push(generateOption(option));
    }
    return results;
  })()).join(' ');
  generateEngineOption = function(engine) {
    return "<span id='" + engine.id + "' class='setting_item'> <img src=" + engine.src + " /> <span class='text'>" + engine.description + "</span> <input class='tgl tgl-flat' id='" + engine.id + "_checkbox' type='checkbox'> <label class='tgl-btn' for='" + engine.id + "_checkbox'></label> </span>";
  };
  engineOptionList = ((function() {
    var j, len, ref, results;
    ref = popData.engines;
    results = [];
    for (j = 0, len = ref.length; j < len; j++) {
      engine = ref[j];
      results.push(generateEngineOption(engine));
    }
    return results;
  })()).join(' ');
  engJSON = '[\n    {\n        id : "UserEngine",\n        title : "Example Engine",\n        description : "Example of user-defined engine",\n        src : "http://lkytal.qiniudn.com/ic.ico",\n        href : "https://www.google.com/search?q=${text}"\n    }\n]';
  chsJSON = '[\n    {\n        id : "UserEngine",\n        title : "Example Engine",\n        description : "自定义引擎实例",\n        src : "http://lkytal.qiniudn.com/ic.ico",\n        href : "https://www.google.com/search?q=${text}"\n    }\n]';
  $("body").append("<div id='popup_setting_bg'> <div id='popup_setting_win'> <div id='popup_title'>PopUp Search Setting</div> <div id='popup_content'> <div id='tabs_box'> <div id='popup_tab1' class='popup_tab popup_selected'>选项 / General</div> <div id='popup_tab2' class='popup_tab'>搜索引擎 / Engines</div> <div id='popup_tab3' class='popup_tab'>自定义 / Customize</div> <div id='popup_tab4' class='popup_tab'>关于 / About</div> </div> <div id='page_box'> <div id='option_box'> <div id='popup_tab1Page'> " + optionList + " </div> <div id='popup_tab2Page'> " + engineOptionList + " </div> <div id='popup_tab3Page'> <div id='editTitle'> <div><b>请阅读帮助 / Read HELP first</b></div> <span id='popHelp'><u>Help</u></span> <span id='popReset'><u>Reset</u></span> </div> <textarea id='popup_engines'></textarea> </div> <div id='popup_tab4Page'> <h3>Authured by Lkytal</h3> <p> You can redistribute it under <a href='http://creativecommons.org/licenses/by-nc-sa/4.0/'> Creative Commons Attribution-NonCommercial-ShareAlike Lisence </a> </p> <p class='contact-line'> Source Code at<br> Git OSChina <a class='tab-text' href='https://git.oschina.net/coldfire/GM'> https://git.oschina.net/coldfire/GM </a> <br /> Github <a class='tab-text' href='https://github.com/lkytal/GM'> https://github.com/lkytal/GM </a> </p> <p> Contact:<br> Github <a class='tab-text' href='https://github.com/lkytal'> https://github.com/lkytal/ </a> <br> Greasy fork <a class='tab-text' href='https://greasyfork.org/en/users/152-lkytal'> https://greasyfork.org/en/users/152-lkytal </a> </p> </div> </div> <div id='btnarea'> <div id='popup_save' class='setting_btn'>Save</div> <div id='popup_close' class='setting_btn'>Close</div> </div> </div> </div> </div> <div id='popup_help_bg'> <div id='popup_help_win'> <div id='popup_help_content'> <div id='helplang'> <span id='engHead' class='popup_head_selected'>English</span> <span id='chsHead'>中文</span> </div> <div id='help_box'> <div id='engContent'> The content of custom engine should be in standard JSON format, in forms of following: <pre> " + engJSON + " </pre> The 'id' should be unique for every entry and must NOT contain any space character , the 'title' and the 'description' can be any text you like, the 'src' indicates the icon of every entry, should be the url to an image or a <a href='http://dataurl.net/#about'>DataURL</a>. The 'href' is the link to be open upon click, you may have noticed the '${text}' variable, which will be replaced by selected text or other strings, the avaliable variables are: <br><br> ${text} : will be replaced by selected text (Url encoded, should use this in default)<br> ${rawText} : will be replaced by untouched selected text<br> ${domain} : will be replaced by corrent url\'s domain<br> ${url} : will be replaced by corrent webpage\'s url<br> <br> Note: You can't modify built-in engines directly, however, you can disable them and add your own. </div> <div id='chsContent'> 自定义引擎内容应当是合法的JSON格式, 如下 <pre> " + chsJSON + " </pre> 每一项的 id 必须各不相同且不能含有空格, title 和 description 可以随意填写, src 是该项的图标, 可以是指向图标的 url 或者是一个 <a href='http://dataurl.net/#about'>DataURL</a>. href 是引擎的 url 链接, 其中可以包含诸如 ${text} 这样的变量, 可用的变量有:<br><br> ${text} : 代表选中文字, 经过 url encoding, 一般应当使用此项<br> ${rawText} : 代表未经 encoding 的原始选中文字<br> ${domain} : 代表当前页面的域名<br> ${url} : 代表当前页面的 url 地址<br> <br> 注意: 内置引擎无法直接修改, 你可以禁用它们然后添加你自定义的引擎 </div> </div> <div id='help_btnarea'> <div id='popup_help_close' class='setting_btn'>Close</div> </div> </div> </div> </div> </div>");
  $("#popup_setting_bg, #popup_help_bg").hide();
  $("#tabs_box > .popup_tab").on("click", function(e) {
    $("#tabs_box > .popup_tab").removeClass("popup_selected");
    $(this).addClass("popup_selected");
    $("#option_box > div").hide();
    return $("#" + $(this).attr("id") + "Page").show();
  });
  $("#option_box > div").hide();
  $("#tabs_box > .popup_tab.popup_selected").click();
  $("#chsContent").hide();
  $("#engHead").on('click', function(event) {
    $("#engHead").addClass("popup_head_selected");
    $("#chsHead").removeClass("popup_head_selected");
    $("#engContent").show();
    return $("#chsContent").hide();
  });
  $("#chsHead").on('click', function(event) {
    $("#engHead").removeClass("popup_head_selected");
    $("#chsHead").addClass("popup_head_selected");
    $("#engContent").hide();
    return $("#chsContent").show();
  });
  ref = $("#popup_setting_win .setting_item");
  for (j = 0, len = ref.length; j < len; j++) {
    item = ref[j];
    if (item != null) {
      ReadOpt(item.id);
    }
  }
  $("#popup_engines").val(GM_getValue("engineString", popData.defaultEngineString));
  $("#popReset").click(function() {
    if (confirm("Reset?")) {
      return $("#popup_engines").val(popData.defaultEngineString);
    }
  });
  $("#popHelp").click(function() {
    return $("#popup_help_bg").fadeIn();
  });
  if (!GetOpt("userEngine_st")) {
    $("#popup_tab3").hide();
  }
  $("#popup_save").click(function() {
    var k, len1, ref1, userEngineString;
    ref1 = $("#popup_setting_win .setting_item");
    for (k = 0, len1 = ref1.length; k < len1; k++) {
      item = ref1[k];
      if (item != null) {
        SaveOpt(item.id);
      }
    }
    userEngineString = $("#popup_engines").val();
    if (userEngineString !== "") {
      try {
        popData.userEngines = JSON.parse(userEngineString);
        GM_setValue("engineString", userEngineString);
      } catch (error) {
        alert("搜索列表错误!请检查\nEngine config Error!");
        log(userEngineString);
      }
    }
    return $("#popup_setting_bg").fadeOut(300, function() {
      $("#popup_setting_bg").remove();
      return PopupInit();
    });
  });
  $("#popup_close, #popup_setting_bg").click(function() {
    return $("#popup_setting_bg").fadeOut(300, function() {
      return $("#popup_setting_bg").remove();
    });
  });
  $("#popup_help_bg, #popup_help_close").on("click", function(e) {
    return $("#popup_help_bg").fadeOut();
  });
  return $('#popup_setting_win, #popup_help_win, #popup_help_bg').click(function(e) {
    return e.stopPropagation();
  });
};

UpdateLog = function() {
  addAditionalCSS();
  $("body").append("<div id='popup_update_bg'> <div id='popup_update_win'> <div id='update_header'> Popup Search Updated (ver 4.1.0) </div> <div id='popup_update_content'> <div id='update_texts'> <p> <h3>此版本引入的重要改变:</h3> <p> 自定义引擎功能开放, 点击 'Open setting' 可以打开设置并启用该功能. 请记得在自定义前请点击'HELP'按钮以阅读帮助文档. </p> <p> 注意: 启用自定义引擎后, 重新打开设置窗口才会生效. </p> </p> <p> <h3>What's new in this version:</h3> <p> You can customize your own engines now. Click 'Open setting' to check it out. Remember to read 'HELP' before edit. </p> <p> Note: After you enabled customization, reopen setting window to take effect. </p> </p> </div> <div id='update_btnarea'> <div id='popup_update_open' class='setting_btn'>Open Setting</div> <div id='popup_update_close' class='setting_btn'>Close</div> </div> </div> </div> </div>");
  $('#popup_update_open').on('click', function(event) {
    UpdateNotificated();
    $("#popup_update_bg").hide();
    OpenSet();
  });
  return $('#popup_update_close').on('click', function(event) {
    UpdateNotificated();
    $("#popup_update_bg").hide();
  });
};

UpdateNotificated = function() {
  return GM_setValue("UpdateAlert", popData.codeVersion);
};

PopupLoad = function() {
  var engine, j, k, len, len1, option, popupmenu, ref, ref1, setDefault, userEngineString;
  if (window.self !== window.top || window.frameElement) {
    if (!GM_getValue("Iframe_st", 0)) {
      return;
    }
  }
  addCSS();
  if (GM_getValue("UpdateAlert", 0) < popData.codeVersion) {
    setDefault = function(key, defaultValue) {
      return GM_setValue(key, GM_getValue(key, defaultValue));
    };
    ref = popData.optionList;
    for (j = 0, len = ref.length; j < len; j++) {
      option = ref[j];
      setDefault(option.id, option.defaultValue);
    }
    ref1 = popData.engines;
    for (k = 0, len1 = ref1.length; k < len1; k++) {
      engine = ref1[k];
      setDefault(engine.id, engine.defaultState);
    }
    UpdateLog();
  }
  popData.defaultEngineString = JSON.stringify(popData.defaultEngines, null, 4);
  if (GetOpt("userEngine_st")) {
    userEngineString = GM_getValue("engineString", popData.defaultEngineString);
    try {
      popData.userEngines = JSON.parse(userEngineString);
    } catch (error) {
      log(userEngineString);
    }
  }
  PopupInit();
  GM_registerMenuCommand("Popup Search Setting / 设置", OpenSet, 'p');
  if (GM_getValue("PopupMenu", 0)) {
    popupmenu = document.body.appendChild(document.createElement("menu"));
    popupmenu.outerHTML = '<menu id="userscript-popup" type="context"><menuitem id="Popupset" label="Popup Search设置"></menuitem></menu>';
    document.querySelector("#Popupset").addEventListener("click", OpenSet, false);
    return $(document).on("contextmenu", function() {
      return document.body.setAttribute("contextmenu", "userscript-popup");
    });
  }
};

setTimeout(PopupLoad, 100);

addCSS = function() {
  return GM_addStyle("#ShowUpBox { all: unset; width: auto; height: auto; position: absolute; z-index: 10240; color: black; display: inline-block; line-height: 0; vertical-align: baseline; box-sizing: content-box; } #showupbody { min-width: 20px; max-width: 750px; min-height: 20px; max-height: 500px; display: block; border:solid 2px rgb(144,144,144); border-radius:1px; background:rgba(252, 252, 252, 1); } #popupwapper { all: unset; margin: 3px 2px 3.8px 2px; display:block; line-height: 0; font-size:0; } #Gspan { line-height: normal; width: auto; font-size: 16px; overflow: auto; display: none; } #ShowUpBox img { all: unset; margin: 0px 2px; height: 24px; width: 24px; border-radius: 0px; padding: 0px; display: inline-block; transition-duration: 0.1s; -moz-transition-duration: 0.1s; -webkit-transition-duration: 0.1s; } #ShowUpBox img:hover { margin: -1px 1px -1px 1px; height: 26px; width: 26px; } #popuptip { display: inline-block; clear: both; height: 9px; width: 9px; } .tipup { background: url(" + popData.icons.tipup + ") 0px 0px no-repeat transparent; margin-top: -2px; margin-bottom: 0px; } .tipdown { background: url(" + popData.icons.tipdown + ") 0px 0px no-repeat transparent; margin-top: 0px; margin-bottom: -2px; } #ShowUpBox a { text-decoration: none; display: inline-block; }");
};

addAditionalCSS = function() {
  if (popData.additionalCSSLoaded === 1) {
    return;
  }
  popData.additionalCSSLoaded = 1;
  return GM_addStyle("#popup_setting_bg { all: unset; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.2); position: fixed; left: 0px; top: 0px; z-index:102400; font-family: \"Hiragino Sans GB\", \"Microsoft Yahei\", Arial, sans-serif; display: -webkit-flex; display: flex; justify-content: center; align-items: center; } #popup_setting_win { all: unset; width: 760px; height: 90%; box-shadow: 0 0 10px #222; box-sizing: content-box !important; background: rgba(255, 255, 255, 0.98); overflow: hidden; display: -webkit-flex; display: -moz-flex; display: flex; flex-direction: column; } #popup_title { font-size:24px; font-weight: bold; text-align: center; padding: 15px; background: #16A085; color: white; flex-shrink: 0; height: 40px; } #popup_content { flex-grow: 1; flex-shrink: 1; height: calc(100% - 70px); padding: 0px; display: -webkit-flex; display: -moz-flex; display: flex; justify-content: space-between; align-items: stretch; } #tabs_box { display: -webkit-flex; display: -moz-flex; display: flex; flex-direction: column; flex-basis: 25%; flex-shrink: 0; background: #EEE; } .popup_tab { width: 100%; background: #EEE; padding: 15px; font-weight: bold; text-align: center; box-sizing: border-box; cursor: pointer; user-select: none; -moz-user-select: none; -webkit-user-select: none; } .popup_tab:hover { background: #ccc; } .popup_selected { border-right: none; background: #FFF; } .popup_selected:hover { background: #FFF; } #page_box { padding: 20px 30px; flex-grow: 1; flex-shrink: 1; max-height: 100%; display: -webkit-flex; display: -moz-flex; display: flex; flex-direction: column; } #option_box { display: -webkit-flex; display: -moz-flex; display: flex; flex-direction: column; align-items: stretch; flex-grow: 1; flex-shrink: 1; overflow-y: auto; } #option_box > div { scroll-behavior: smooth; flex-grow: 1; display: -webkit-flex; display: -moz-flex; display: flex; flex-direction: column; align-items: stretch; } #popup_engines { flex-grow: 1; border: solid 2px #ddd; text-overflow: clip; white-space: pre; overflow-x: auto; overflow-y: auto; word-wrap: break-word; resize: none; } #editTitle { padding: 0px 0px 15px 0px; display: -webkit-flex; display: -moz-flex; display: flex; justify-content: space-between; } #editTitle div { flex-grow: 1; } #editTitle span { margin-left: 20px; color : #1ABC9C; cursor: pointer; } #btnarea { display: -webkit-flex; display: -moz-flex; display: flex; justify-content: flex-end; margin-top: 20px; flex-shrink: 0; } .setting_btn { display: inline-block; font-size: 16px; text-align: center; mix-width: 50px; padding: 4px 10px 4px 10px; border-radius: 2px; margin: 0px 0px 0px 20px; background: #1ABC9C; color: #fff; cursor: pointer; user-select: none; -moz-user-select: none; -webkit-user-select: none; } .setting_btn:hover { text-shadow: 0px 0px 2px #FFF; } .setting_item { min-height: 28px; font-size: 14px; margin: 5px 0px 10px 0px; display: -webkit-flex; display: -moz-flex; display: flex; align-items: center; } .setting_item > img { width: 24px; height: auto; margin-right: 7px; } .setting_item .text{ flex-grow: 1; font-size: 16px; } #popup_help_bg { all: unset; width: 100%; height: 100%; position: fixed; top: 0; left: 0; background: transparent; display: -webkit-flex; display: flex; justify-content: center; align-items: center; z-index: 10240000; } #popup_help_win { all: unset; width: 650px; height: 80%; box-shadow: 0 0 10px #222; box-sizing: content-box !important; background: rgba(255, 255, 255, 0.98); padding: 20px; display: -webkit-flex; display: flex; flex-direction: column; align-items: stretch; /*overflow: hidden;*/ } #popup_help_content { max-height: 100%; flex-grow: 1; display: -webkit-flex; display: flex; flex-direction: column; align-items: stretch; } #helplang { flex-grow: 0; flex-shrink: 0; display: -webkit-flex; display: flex; border-bottom: solid 1px #ccc; } #helplang span { padding: 8px 30px; margin-bottom: -1px; cursor: pointer; user-select: none; -moz-user-select: none; -webkit-user-select: none; } #helplang span.popup_head_selected { border-top: solid 1px #ccc; border-left: solid 1px #ccc; border-right: solid 1px #ccc; border-bottom: solid 3px #FFF; } #help_box { overflow-y: auto; flex-grow: 1; flex-shrink: 1; margin-top: 15px; } #help_box > div { word-wrap: break-word; } #help_btnarea { flex-grow: 0; flex-shrink: 0; display: -webkit-flex; display: flex; justify-content: flex-end; margin-top: 20px; } #popup_update_bg { all: unset; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.2); position: fixed; left: 0px; top: 0px; z-index: 1024000; font-family: \"Hiragino Sans GB\", \"Microsoft Yahei\", Arial, sans-serif; display: -webkit-flex; display: flex; justify-content: center; align-items: center; } #popup_update_win { all: unset; width: 50%; height: 80%; box-shadow:0 0 10px #222; box-sizing: content-box !important; background: rgba(255, 255, 255, 0.98); overflow: hidden; font-size: 16px; display: -webkit-flex; display: -moz-flex; display: flex; flex-direction: column; } #update_header { font-size: 24px; font-weight: bold; text-align: center; padding: 15px; background: #16A085; color: white; flex-shrink: 0; height: 40px; } #popup_update_content { flex-grow: 1; flex-shrink: 1; height: calc(100% - 70px); overflow: auto; padding: 15px; display: -webkit-flex; display: -moz-flex; display: flex; flex-direction: column; justify-content: space-between; align-items: stretch; } #update_texts{ flex-grow: 1; flex-shrink: 1; } #update_btnarea { flex-grow: 0; flex-shrink: 0; display: -webkit-flex; display: flex; justify-content: flex-end; margin-top: 20px; } #unshown { display: none; } .tgl { display: none; } .tgl, .tgl:after, .tgl:before, .tgl *, .tgl *:after, .tgl *:before, .tgl+.tgl-btn { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } .tgl::-moz-selection, .tgl:after::-moz-selection, .tgl:before::-moz-selection, .tgl *::-moz-selection, .tgl *:after::-moz-selection, .tgl *:before::-moz-selection, .tgl+.tgl-btn::-moz-selection { background: none; } .tgl::selection, .tgl:after::selection, .tgl:before::selection, .tgl *::selection, .tgl *:after::selection, .tgl *:before::selection, .tgl+.tgl-btn::selection { background: none; } .tgl+.tgl-btn { outline: 0; display: inline-block; width: 4em; height: 2em; position: relative; cursor: pointer; } .tgl+.tgl-btn:after, .tgl+.tgl-btn:before { position: relative; display: inline-block; content: \"\"; width: 50%; height: 100%; } .tgl+.tgl-btn:after { left: 0; } .tgl+.tgl-btn:before { display: none; } .tgl:checked+.tgl-btn:after { left: 50%; } .tgl-flat+.tgl-btn { padding: 2px; -webkit-transition: all .2s ease; transition: all .2s ease; background: #fff; border: 4px solid #f2f2f2; border-radius: 2em; } .tgl-flat+.tgl-btn:after { -webkit-transition: all .2s ease; transition: all .2s ease; background: #f2f2f2; content: \"\"; border-radius: 1em; } .tgl-flat:checked+.tgl-btn { border: 4px solid #1ABC9C; } .tgl-flat:checked+.tgl-btn:after { left: 50%; background: #1ABC9C; }");
};

getLastRange = function(selection) {
  var j, rangeNum, ref;
  for (rangeNum = j = ref = selection.rangeCount - 1; ref <= 0 ? j <= 0 : j >= 0; rangeNum = ref <= 0 ? ++j : --j) {
    if (!selection.getRangeAt(rangeNum).collapsed) {
      return selection.getRangeAt(rangeNum);
    }
  }
  return selection.getRangeAt(selection.rangeCount - 1);
};

get_selection_offsets = function(selection) {
  var $test_span, Rect, lastRange, newRange;
  $test_span = $('<span style="display:inline;">x</span>');
  lastRange = getLastRange(selection);
  newRange = document.createRange();
  newRange.setStart(lastRange.endContainer, lastRange.endOffset);
  newRange.insertNode($test_span[0]);
  Rect = $test_span[0].getBoundingClientRect();
  $test_span.remove();
  return [Rect.top + window.scrollY, Rect.left + window.scrollX, 0, 0];
};
